﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Spanner
{
    public partial class UI
    {
        // These functions correspond one-to-one with their JavaScript counterparts.

        /// <summary>
        /// An abstract type representing JavaScript dates.
        /// </summary>
        public sealed class Date { }

        public static Expr<Date> NewDate() { return JSExpr<Date>("(new Date())"); }
        public static Expr<Date> NewDate(Expr<int> milliseconds) { return JSExpr<Date>("(new Date(#))", milliseconds); }
        public static Expr<Date> NewDate(Expr<string> dateString) { return JSExpr<Date>("(new Date(#))", dateString); }
        public static Expr<Date> NewDate(
                Expr<int> year,
                Expr<int> month = null, // Bizarrely, this, and only this, counts from 0.
                Expr<int> day = null,
                Expr<int> hour = null,
                Expr<int> minute = null,
                Expr<int> second = null,
                Expr<int> ms = null
        )
        {
            var fmt = ( ((object)ms != null)     ? "(new Date(#, #, #, #, #, #, #))"
                      : ((object)second != null) ? "(new Date(#, #, #, #, #, #))"
                      : ((object)minute != null) ? "(new Date(#, #, #, #, #))"
                      : ((object)hour != null)   ? "(new Date(#, #, #, #))"
                      : ((object)day != null)    ? "(new Date(#, #, #))"
                      : ((object)month != null)  ? "(new Date(#, #))"
                      : ((object)year != null)   ? "(new Date(#))"
                      :                            "(new Date())"
                      );
            return JSExpr<Date>(fmt, year, month, day, hour, minute, second, ms);
        }
        public static Expr<Date> NewUtcDate(
                Expr<int> year,
                Expr<int> month = null, // Bizarrely, this, and only this, counts from 0.
                Expr<int> day = null,
                Expr<int> hour = null,
                Expr<int> minute = null,
                Expr<int> second = null,
                Expr<int> ms = null
        )
        {
            return NewDate(MillisecondsAtUtcDate(year, month, day, hour, minute, second, ms));
        }
        public static Expr<int> MillisecondsAtUtcDate(
                Expr<int> year,
                Expr<int> month = null, // Bizarrely, this, and only this, counts from 0.
                Expr<int> day = null,
                Expr<int> hour = null,
                Expr<int> minute = null,
                Expr<int> second = null,
                Expr<int> ms = null
        )
        {
            var fmt = ( ((object)ms != null)     ? "Date.UTC(#, #, #, #, #, #, #)"
                      : ((object)second != null) ? "Date.UTC(#, #, #, #, #, #)"
                      : ((object)minute != null) ? "Date.UTC(#, #, #, #, #)"
                      : ((object)hour != null)   ? "Date.UTC(#, #, #, #)"
                      : ((object)day != null)    ? "Date.UTC(#, #, #)"
                      : ((object)month != null)  ? "Date.UTC(#, #)"
                      : ((object)year != null)   ? "Date.UTC(#)"
                      :                            "Date.UTC()"
                      );
            return JSExpr<int>(fmt, year, month, day, hour, minute, second, ms);
        }
        public static Expr<int> ParseDate(Expr<string> dateString)
        {
            return JSExpr<int>("Date.parse(#)", dateString);
        }

        public static Expr<int> GetDate(Expr<Date> x) { return JSExpr<int>("#.getDate()", x); }
        public static Expr<int> GetDay(Expr<Date> x) { return JSExpr<int>("#.getDay()", x); }
        public static Expr<int> GetFullYear(Expr<Date> x) { return JSExpr<int>("#.getFullYear()", x); }
        public static Expr<int> GetHours(Expr<Date> x) { return JSExpr<int>("#.getHours()", x); }
        public static Expr<int> GetMilliseconds(Expr<Date> x) { return JSExpr<int>("#.getMilliseconds()", x); }
        public static Expr<int> GetMinutes(Expr<Date> x) { return JSExpr<int>("#.getMinutes()", x); }
        public static Expr<int> GetMonth(Expr<Date> x) { return JSExpr<int>("#.getMonth()", x); }
        public static Expr<int> GetSeconds(Expr<Date> x) { return JSExpr<int>("#.getSeconds()", x); }
        public static Expr<int> GetTime(Expr<Date> x) { return JSExpr<int>("#.getTime()", x); }
        public static Expr<int> GetTimezoneOffset(Expr<Date> x) { return JSExpr<int>("#.getTimezoneOffset()", x); }
        public static Expr<int> GetUtcDate(Expr<Date> x) { return JSExpr<int>("#.getUTCDate()", x); }
        public static Expr<int> GetUtcDay(Expr<Date> x) { return JSExpr<int>("#.getUTCDay()", x); }
        public static Expr<int> GetUtcFullYear(Expr<Date> x) { return JSExpr<int>("#.getUTCFullYear()", x); }
        public static Expr<int> GetUtcHours(Expr<Date> x) { return JSExpr<int>("#.getUTCHours()", x); }
        public static Expr<int> GetUtcMilliseconds(Expr<Date> x) { return JSExpr<int>("#.getUTCMilliseconds()", x); }
        public static Expr<int> GetUtcMinutes(Expr<Date> x) { return JSExpr<int>("#.getUTCMinutes()", x); }
        public static Expr<int> GetUtcMonth(Expr<Date> x) { return JSExpr<int>("#.getUTCMonth()", x); }
        public static Expr<int> GetUtcSeconds(Expr<Date> x) { return JSExpr<int>("#.getUTCSeconds()", x); }
        public static Expr<string> ToDateString(Expr<Date> x) { return JSExpr<string>("#.toDateString()", x); }
        public static Expr<string> ToLocaleDateString(Expr<Date> x) { return JSExpr<string>("#.toLocaleDateString()", x); }
        public static Expr<string> ToLocaleFormat(Expr<Date> x) { return JSExpr<string>("#.toLocaleFormat()", x); }
        public static Expr<string> ToLocaleString(Expr<Date> x) { return JSExpr<string>("#.toLocaleString()", x); }
        public static Expr<string> ToLocaleTimeString(Expr<Date> x) { return JSExpr<string>("#.toLocaleTimeString()", x); }
        public static Expr<string> ToTimeString(Expr<Date> x) { return JSExpr<string>("#.toTimeString()", x); }
        public static Expr<string> ToUtcString(Expr<Date> x) { return JSExpr<string>("#.toUTCString()", x); }
    }
}
